home *** CD-ROM | disk | FTP | other *** search
- (*
- In article 767298319@stimpy.cs.iastate.edu, james@cs.iastate.edu (James N. Potts) writes:
- >I know that if you place {$D string} in a program, the string will be placed
- >into the executable. Is there an easy way to find this information, or do
- >you have to do a search through the file?
-
- There are a few ways. Screen savers use this information, so one way
- to do it is to rename your file *.scr, place it in the windows directory,
- and then look at it from the control panel as you are selecting a screen
- saver. Yeach! Another way is to use a file dumper (?) such as
- TDUMP by Borland or EXEHDR by Microsoft. These programs will give you
- the pertinent information. TDUMP by the way comes with BP 7.0.
-
- Programmaticly you can obtain the string through the new executable
- file header information. The string you are interested in is the
- first entry in the nonresident-name table. If you do not specify
- {$D string} then this string will be the file name (like myfile.EXE).
-
- A few days ago I posted how to do certain things with the new executable
- file header. You may want to look back a few days on your news reader
- to get some insight. But don't dispare. I will give some clues here.
-
- The first thing to do is to read the new EXE file format found
- in the Borland or Micrsoft help files. For Borland it can
- be found under the "File Formats" topic.
-
- Next you should get the EXE header types. This can be obtained
- at ftp.microsoft.com (filename: newexe12.zip). I have
- included a Pascal version at the end of this missive.
-
- Now in your program you need to do the following:
-
- 1. Determine if the file is of the new EXE type.
- 2. Get the address of the non-resident name table.
- 3. Read the first string in the non-resident name table.
-
- Later in this missive you will find a function that does step 1.
- Below are the steps
- *)
-
- uses
- WinCrt,
- WinTypes,
- WinProcs;
-
- const
- fn: PChar = 'c:\bp\myprog\myprog.exe';
-
- type
- DosHdr : IMAGE_DOS_HEADER;
- NewHdr : IMAGE_NEW_HEADER;
- ModuleDescription: rsrc_string;
- Filehandle : Integer;
- ofs : TOFSTRUCT;
-
- label
- Return;
-
- begin
- if not IsNewExe (fn, DosHdr, NewHdr) then goto Return;
-
- FillChar (ofs, sizeof (TOFSTRUCT), 0);
- if OpenFile (fn, ofs, OF_EXIST or OF_READ) = -1 then goto Return;
-
- FileHandle := OpenFile (fn, ofs, OF_REOPEN or OF_READ);
- if FileHandle = -1 then goto Return;
-
- { goto location of non-resident name table }
- _llseek (FileHandle, DosHdr.e_lfanew + NewHdr.ne_nrestab, 0);
-
- { read length of string (in first entry of the non-resident name table) }
- _lread (FileHandle, @ModuleDescription.rs_len, sizeof (Byte));
-
- { allocate space for string }
- GetMem (ModuleDescription.rs_string, ModuleDescription.rs_len + 1);
-
- { read module description string }
- _lread (FileHandle, @ModuleDescription.rs_string, ModuleDescription.rs_len);
-
- { tag null termination onto string }
- ModuleDescription.rs_string[ModuleDescription.rs_len] := #0;
-
- { write results }
- writeln (fn, ' Module Description: ', ModuleDescription.rs_string);
-
- { dispose of string }
- FreeMem (ModuleDescription.rs_string, ModuleDescription.rs_len + 1);
-
- Return:
- { close file }
- _lclose (FileHandle);
- end.
-
-
- Note that the above code is only good for finding the first string
- in the non-resident name table as the rest of the table also includes
- index numbers as wll as the string length and the string. This code
- has also not been tested.
-
- I hope you get some mileage from it.
-
- -Michael Vincze
- vincze@lobby.ti.com
-
- ---------- NEW EXE HEADER TYPES ----------
-
- type
- IMAGE_DOS_HEADER = record { DOS 1, 2, 3 .EXE header }
- e_magic : Word; { Magic number }
- e_cblp : Word; { Words on last page of file }
- e_cp : Word; { Pages in file }
- e_crlc : Word; { Relocations }
- e_cparhdr : Word; { Size of header in paragraphs }
- e_minalloc: Word; { Minimum extra paragraphs needed }
- e_maxalloc: Word; { Maximum extra paragraphs needed }
- e_ss : Word; { Initial (relative) SS value }
- e_sp : Word; { Initial SP value }
- e_csum : Word; { Checksum }
- e_ip : Word; { Initial IP value }
- e_cs : Word; { Initial (relative) CS value }
- e_lfarlc : Word; { File address of relocation table }
- e_ovno : Word; { Overlay number }
- e_res : array[0..3] of Word; { Reserved words }
- e_oemid : Word; { OEM identifier (for e_oeminfo) }
- e_oeminfo : Word; { OEM information; e_oemid specific }
- e_res2 : array[0..9] of Word; { Reserved words }
- e_lfanew : Longint; { File address of new exe header }
- end;
-
- const
- IMAGE_DOS_SIGNATURE = $00005A4D; { MZ }
- IMAGE_OS2_SIGNATURE = $0000454E; { NE }
- IMAGE_OS2_SIGNATURE_LE = $00005A4D; { LE }
- IMAGE_NT_SIGNATURE = $00004550; { PE00 }
-
- type
- IMAGE_NEW_HEADER = record { New .EXE header }
- ne_magic : Word; { Magic number NE_MAGIC }
- ne_ver : Byte; { Version number }
- ne_rev : Byte; { Revision number }
- ne_enttab : Word; { Offset of Entry Table }
- ne_cbenttab : Word; { Number of bytes in Entry Table }
- ne_crc : Longint; { Checksum of whole file }
- ne_flags : Word; { Flag word }
- ne_autodata : Word; { Automatic data segment number }
- ne_heap : Word; { Initial heap allocation }
- ne_stack : Word; { Initial stack allocation }
- ne_csip : Longint; { Initial CS:IP setting }
- ne_sssp : Longint; { Initial SS:SP setting }
- ne_cseg : Word; { Count of file segments }
- ne_cmod : Word; { Entries in Module Reference Table }
- ne_cbnrestab : Word; { Size of non-resident name table }
- ne_segtab : Word; { Offset of Segment Table }
- ne_rsrctab : Word; { Offset of Resource Table }
- ne_restab : Word; { Offset of resident name table }
- ne_modtab : Word; { Offset of Module Reference Table }
- ne_imptab : Word; { Offset of Imported Names Table }
- ne_nrestab : Longint; { Offset of Non-resident Names Table }
- ne_cmovent : Word; { Count of movable ent }
- ne_align : Word; { Segment alignment shift count }
- ne_cres : Word; { Count of resource entries }
- ne_exetyp : Byte; { Target operating system }
- ne_flagsothers: Byte; { Other .EXE flags }
- ne_res : array [0..7] of Byte; { Pad structure to 64 bytes }
- end;
-
- const { Format of ne_exetyp (target operating system) }
- NE_UNKNOWN = $0; { Unknown (any "new-format" OS) }
- NE_OS2 = $1; { Microsoft/IBM OS/2 }
- NE_WINDOWS = $2; { Microsoft Windows }
- NE_DOS4 = $3; { Microsoft MS-DOS 4.x }
- NE_DEV386 = $4; { Microsoft Windows 386 }
-
- const { Format of IMAGE_NEW_HEADER.ne_flags }
- NENOTP = $8000; { Not a process }
- NEIERR = $2000; { Errors in image }
- NEBOUND = $0800; { Bound as family app }
- NEAPPTYP = $0700; { Application type mask }
- NENOTWINCOMPAT = $0100; { Not compatible with P.M. Windowing }
- NEWINCOMPAT = $0200; { Compatible with P.M. }
- NEWINAPI = $0300; { Uses P.M. Windowing API }
- NEFLTP = $0080; { Floating-point instructions }
- NEI386 = $0040; { 386 instructions }
- NEI286 = $0020; { 286 instructions }
- NEI086 = $0010; { 8086 instructions }
- NEPROT = $0008; { Runs in protected mode only }
- NEPPLI = $0004; { Per-Process Library Initialization }
- NEINST = $0002; { Instance data }
- NESOLO = $0001; { Solo data }
-
- type
- new_seg = record { New .EXE segment table entry }
- ns_sector : Word; { File sector of start of segment }
- ns_cbseg : Word; { Number of bytes in file }
- ns_flags : Word; { Attribute flags }
- ns_minalloc: Word; { Minimum allocation in bytes }
- end;
-
- const { Format of new_seg.nsflags }
- NSCODE = $0000; { Code segment }
- NSDATA = $0001; { Data segment }
- NSLOADED = $0004; { ns_sector field contains memory addr }
- NSTYPE = $0007; { Segment type mask }
- NSITER = $0008; { Iterated segment flag }
- NSMOVE = $0010; { Movable segment flag }
- NSSHARED = $0020; { Shared segment flag }
- NSPRELOAD = $0040; { Preload segment flag }
- NSEXRD = $0080; { Execute-only (code segment), or read-only (data segment) }
- NSRELOC = $0100; { Segment has relocations }
- NSCONFORM = $0200; { Conforming segment }
- NSDISCARD = $1000; { Segment is discardable }
- NS32BIT = $2000; { 32-bit code segment }
- HSHUGE = $4000; { Huge memory segment }
- NSEXPDOWN = $0200; { Data segment is expand down }
-
- (*
- #define NSDPL 0x0C00 /* I/O privilege level (286 DPL bits) */
- #define SHIFTDPL 10 /* Left shift count for */
- #define NSPURE NSSHARED /* For compatibility */
- #define NSALIGN 9 /* Segment data aligned on 512 byte boundaries */
- *)
-
- type
- new_rlcinfo = record { Relocation info }
- nr_nreloc: Word; { number of relocation items that follow }
- end;
-
- type
- new_rlc = record { Relocation item }
- nr_stype: Byte; { Source type }
- nr_flags: Byte; { Flag byte }
- nr_soff : Word; { Source offset }
- case Integer of
- 0: (nr_segno : Byte; { Target segment number } { internal reference }
- nr_res : Byte; { Reserved }
- nr_entry : Word); { Target Entry Table offset }
- 1: (nr_mod : Word; { Index into Module Reference Table } { import }
- nr_proc : Word); { Procedure ordinal or name offset }
- 2: (nr_ostype: Word; { OSFIXUP type } { operating system fixup }
- nr_osres : Word); { Reserved }
- end;
-
- { Resource type or name string
- }
- type
- rsrc_string = record
- rs_len : Byte; { number of bytes in string }
- rs_string: PChar; { text of string }
- end;
-
-
- ---------- IsNewExe() function ----------
-
- Below is the code to determine if the file is of the new EXE type.
- Note how DosHdr and NewHdr are passed by reference and not by value.
- This is so values for DosHdr and NewHdr can be used by other
- functions called by the main program. Also note the extensive use
- of the OpenFile(), _lread(), _llseek(), and _lclose() functions.
-
- function IsNewExe (fn: PChar;
- var DosHdr: IMAGE_DOS_HEADER;
- var NewHdr: IMAGE_NEW_HEADER): Boolean;
- label
- Return;
- var
- Filehandle: Integer;
- BytesRead : Integer;
- ofs : TOFSTRUCT;
- begin
- IsNewExe := False;
-
- FillChar (ofs, sizeof (TOFSTRUCT), 0);
- if OpenFile (fn, ofs, OF_EXIST or OF_READ) = -1 then goto Return;
-
- FileHandle := OpenFile (fn, ofs, OF_REOPEN or OF_READ);
- if FileHandle = -1 then goto Return;
-
- FillChar (DosHdr, sizeof (IMAGE_DOS_HEADER), 0);
- FillChar (NewHdr, sizeof (IMAGE_NEW_HEADER), 0);
-
- { read MS-DOS header }
- BytesRead := _lread (FileHandle, @DosHdr, sizeof (IMAGE_DOS_HEADER));
-
- { test for bytes read }
- if BytesRead <> sizeof (IMAGE_DOS_HEADER) then goto Return;
-
- { test for magic number MZ }
- if DosHdr.e_magic <> IMAGE_DOS_SIGNATURE then goto Return;
-
- { test for address of new exe header }
- if DosHdr.e_lfanew <= 0 then goto Return;
-
- { fast forward to Windows header }
- if _llseek (FileHandle, DosHdr.e_lfanew, 0) = -1 then goto Return;
-
- { read new exe header }
- BytesRead := _lread (FileHandle, @NewHdr, sizeof (IMAGE_NEW_HEADER));
-
- { test for bytes read }
- if BytesRead <> sizeof (IMAGE_NEW_HEADER) then goto Return;
-
- { test for signature NE }
- if NewHdr.ne_magic <> IMAGE_OS2_SIGNATURE then goto Return;
-
- { passed the test }
- IsNewExe := True;
-
- Return:
- { close file }
- _lclose (FileHandle);
- end;
-